/**
 * There are <a href="https://github.com/thinkgem/jeesite">JeeSite</a> code generation
 */
package com.chlitina.store.modules.base.web;

import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import javax.validation.ConstraintViolationException;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.chlitina.store.common.beanvalidator.BeanValidators;
import com.chlitina.store.common.config.Global;
import com.chlitina.store.common.mapper.JsonMapper;
import com.chlitina.store.common.persistence.Page;
import com.chlitina.store.common.utils.DateUtils;
import com.chlitina.store.common.utils.FileUtils;
import com.chlitina.store.common.utils.StringUtils;
import com.chlitina.store.common.utils.excel.ExportExcel;
import com.chlitina.store.common.utils.excel.ImportExcel;
import com.chlitina.store.common.web.BaseController;
import com.chlitina.store.modules.base.entity.Customer;
import com.chlitina.store.modules.base.entity.CustomerEmployeeRelationship;
import com.chlitina.store.modules.base.service.CustomerEmployeeRelationshipService;
import com.chlitina.store.modules.base.service.CustomerService;
import com.chlitina.store.modules.cash.entity.StoreConsume;
import com.chlitina.store.modules.cash.model.Member;
import com.chlitina.store.modules.cash.model.MemberConsumeDetail;
import com.chlitina.store.modules.cash.service.MemberService;
import com.chlitina.store.modules.cash.service.StoreConsumeService;
import com.chlitina.store.modules.employee.service.EmployeeService;
import com.chlitina.store.modules.expert.service.CustomerExamService;
import com.chlitina.store.modules.expert.utils.ExpertUtils;
import com.chlitina.store.modules.sys.entity.Store;
import com.chlitina.store.modules.sys.utils.StoreUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;

/**
 * 客户Controller
 * 
 * @author lvbo
 * @version 2013-07-03
 */
@Controller
@RequestMapping(value = Global.ADMIN_PATH + "/base/customer")
public class CustomerController extends BaseController {

	@Autowired
	private CustomerService customerService;
	@Autowired
	private CustomerExamService customerExamService;
	@Autowired
	private CustomerEmployeeRelationshipService customerEmployeeRelationshipService;
	@Autowired
	private EmployeeService employeeService;
	@Autowired
	private MemberService memberService;
	@Autowired
	private StoreConsumeService storeConsumeService;

	@ModelAttribute
	public Customer get(@RequestParam(required = false) Long id) {
		if (id != null) {
			return customerService.get(id);
		} else {
			return new Customer();
		}
	}
	
	@RequestMapping(value = "search")
	public String search(Customer customer, HttpServletRequest request,
			HttpServletResponse response, Model model) {
		Store store = StoreUtils.getStore();
		String customerExamId = request.getParameter("ceid");
		String type = request.getParameter("searchType");
		String keyWord = request.getParameter("keyWord");
		if (store != null) {
			customer.setStore(store);
		}
		Page<Customer> page = customerService.find(new Page<Customer>(request,
				response), type, keyWord);
		Map<Long, Boolean> hasExpert = Maps.newHashMap();
		for (Customer c : page.getList()) {
			boolean bool = customerExamService.hasExpert(c.getId());
			hasExpert.put(c.getId(), bool);
		}
		model.addAttribute("hasExpert", hasExpert);
		model.addAttribute("page", page);
		String ifshow = request.getParameter("show");
		if (ifshow != null && !ifshow.equals("")) {
			String showTime = request.getParameter("showTime");
			model.addAttribute("ifshow", true);
			model.addAttribute("showTime", showTime);
			model.addAttribute("customerExamId", customerExamId);
		} else {
			model.addAttribute("ifshow", false);
			model.addAttribute("showTime", 0);
			model.addAttribute("customerExamId", customerExamId);
		}
		model.addAttribute("keyWord", keyWord);
		model.addAttribute("searchType", type);
		model.addAttribute("customerName", customer.getName());
		return "modules/expert/customerSelect";
	}

	@ResponseBody
	@RequestMapping(value = "getListJson")
	public String getListJson(HttpServletRequest request,
			HttpServletResponse response, Model model) {
		String type = request.getParameter("searchType");
		String keyWord = request.getParameter("keyWord");
		Page<Customer> page = customerService.find(new Page<Customer>(request,
				response), type, keyWord);
		Set<Map<String, Object>> set = Sets.newHashSet();
		List<Customer> customerList = page.getList();
		for (Customer c : customerList) {
			Map<String, Object> map = Maps.newHashMap();
			map.put("id", c.getId());
			map.put("name", c.getName());
			map.put("nickName", c.getNickname());
			map.put("weight", c.getWeight());
			map.put("mobile", StringUtils.replaceTel(c.getMobile()));
			map.put("ages", DateUtils.getAge(c.getBirthday()));
			set.add(map);
		}
		return JsonMapper.getInstance().toJson(set);
	}
	
	@RequestMapping(value = { "list", "" })
	public String list(Customer customer, HttpServletRequest request,
			HttpServletResponse response, Model model) {
		Store store = StoreUtils.getStore();
		String type = request.getParameter("searchType");
		String keyWord = request.getParameter("keyWord");
		if (store != null) {
			customer.setStore(store);
		}
		Page<Customer> page = customerService.find(new Page<Customer>(request,
				response), type, keyWord);
		model.addAttribute("searchType", type);
		model.addAttribute("keyWord", keyWord);
		model.addAttribute("page", page);
		return "modules/base/customerList";
	}

	@RequestMapping(value = "form")
	public String form(Customer customer,HttpServletRequest request, Model model) {
		Date birthday = customer.getBirthday();
		if (birthday != null) {
			java.sql.Date sqlDate = new java.sql.Date(birthday.getTime());
			customer.setBirthday(sqlDate);
		}
		List<CustomerEmployeeRelationship> ceList = Lists.newArrayList();
		if (customer != null && customer.getId() != null) {
			ceList = customerEmployeeRelationshipService
					.findByCustomer(customer.getId());
			model.addAttribute("ceList", ceList);
		}
		Map<Long, String> otherEmployees = Maps.newHashMap();
		Map<Long, String> employee = ExpertUtils.getEmployee();
		Set<Long> keySet = employee.keySet();
		for (Long key : keySet) {
			boolean isSelect = false;
			for (CustomerEmployeeRelationship cer : ceList) {
				if (cer.getEmployee().getId().equals(key)) {
					isSelect = true;
					break;
				}
			}
			if (!isSelect) {
				otherEmployees.put(key, employee.get(key));
			}
		}
		model.addAttribute("target", request.getParameter("target"));
		model.addAttribute("otherList", otherEmployees);
		model.addAttribute("customer", customer);
		return "modules/base/customerForm";
	}

	@RequestMapping(value = "detail")
	public String detail(HttpServletRequest request, Customer customer, Model model) {
		Date birthday = customer.getBirthday();
		if (birthday != null) {
			java.sql.Date sqlDate = new java.sql.Date(birthday.getTime());
			customer.setBirthday(sqlDate);
		}
		String emsId = request.getParameter("emsId");
		if (emsId != null) {
			model.addAttribute("emsId", emsId);
		}
		List<CustomerEmployeeRelationship> ceList = customerEmployeeRelationshipService
				.findByCustomer(customer.getId());
		model.addAttribute("ceList", ceList);
		model.addAttribute("customer", customer);
		return "modules/base/customerDetail";
	}
	@RequestMapping(value = "cards")
	public String cards(HttpServletRequest request, Customer customer, Model model) {
		HttpSession session = request.getSession();
		Long cid = (Long)session.getAttribute("customerId");
		Customer c = customerService.get(cid);
		Member member = (Member)session.getAttribute("member");
		if (member == null || !cid.equals(member.getCustomer().getId())) {
			member = new Member();
			member.setCustomer(c);
		}
		memberService.loadingMemberInfo(member);
		model.addAttribute("member", member);
		return "modules/base/customerCardDetail";
	}
	@RequestMapping(value = "consume")
	public String consume(HttpServletRequest request,HttpServletResponse response, Customer customer, Model model) {
		HttpSession session = request.getSession();
		Long cid = (Long)session.getAttribute("customerId");
		Page<StoreConsume> page = new Page<StoreConsume>(request, response);
		List<StoreConsume> list = storeConsumeService.findByCustomer(cid);
		page.updatePage(list);
		model.addAttribute("page", page);
		return "modules/base/customerConsumeList";
	}
	@RequestMapping(value = "consumeDetail")
	public String consumeDetail(@RequestParam("consumeId") String consumeId, HttpServletRequest request, Model model) {
		HttpSession session = request.getSession();
		String target = (String)session.getAttribute("target");
		MemberConsumeDetail consumeInfo = memberService.loadMemberConsumeInfo(consumeId);
		model.addAttribute("consumeInfo", consumeInfo);
		model.addAttribute("target", target);
		return "modules/base/customerConsumeDetail";
	}

	@RequestMapping(value = "save")
	public String save(Customer customer, Model model,
			HttpServletRequest request, RedirectAttributes redirectAttributes) {
		String[] employees = request.getParameterValues("personalEmployee");
		if (!beanValidator(model, customer)) {
			return form(customer, request, model);
		}
		Long id = customer.getId();
		customerService.save(customer);
		// 原有的关系
		List<Long> oldRelationship = Lists.newArrayList();
		List<CustomerEmployeeRelationship> cerList = customerEmployeeRelationshipService
				.findByCustomer(customer.getId());
		for (CustomerEmployeeRelationship cer : cerList) {
			oldRelationship.add(cer.getEmployee().getId());
		}
		// 修改后的关系
		List<Long> newRelationship = Lists.newArrayList();
		if (employees != null && employees.length > 0) {
			for (String eid : employees) {
				Long employeeId = null;
				try {
					employeeId = Long.parseLong(eid);
				} catch (NumberFormatException e) {
					continue;
				}
				newRelationship.add(employeeId);
			}
		}
		// 需要删除的关系
		List<Long> deleteRelationship = Lists.newArrayList();
		for (Long or : oldRelationship) {
			if (!newRelationship.contains(or)) {
				deleteRelationship.add(or);
			}
		}
		// 需要新增加的关系
		List<Long> addRelationship = Lists.newArrayList();
		for (Long or : newRelationship) {
			if (!oldRelationship.contains(or)) {
				addRelationship.add(or);
			}
		}
		// 添加和删除
		for (Long ar : addRelationship) {
			CustomerEmployeeRelationship cer = new CustomerEmployeeRelationship();
			cer.setCustomer(customer);
			cer.setEmployee(employeeService.get(ar));
			customerEmployeeRelationshipService.save(cer);
		}
		for (Long dr : deleteRelationship) {
			customerEmployeeRelationshipService.delete(customer.getId(), dr);
		}
		if (id == null) {
			addMessage(redirectAttributes, "添加客户" + customer.getName() + "成功");
			String target = request.getParameter("target");
			if (target != null && !"".equals(target)) {
				//在收银界面添加客户，成功后返回收银界面
				return "redirect:" + Global.ADMIN_PATH + "/" + target;
			} else {
				//在客户管理页面新添加的客户，成功后返回客户列表
				return "redirect:" + Global.ADMIN_PATH + "/base/customer/";
			}
		} else {
			addMessage(redirectAttributes, "修改客户" + customer.getName() + "成功");
			//客户修改后返回客户明细
			return "redirect:" + Global.ADMIN_PATH + "/base/customer/detail?id=" + customer.getId();
		}
	}

	@RequestMapping(value = "delete")
	public String delete(Long id, RedirectAttributes redirectAttributes) {
		try {
			customerService.delete(id);
			addMessage(redirectAttributes, "删除客户成功");
		} catch (Exception e) {
			addMessage(redirectAttributes, "无法删除此客户");
		}
		return "redirect:" + Global.ADMIN_PATH + "/base/customer/";
	}

	@RequestMapping(value = "export")
	public String exportFile(HttpServletRequest request,
			HttpServletResponse response, RedirectAttributes redirectAttributes) {
		String fileName = "";
		String errorMsg = "";
		ExportExcel writeFile = null;
		try {
			String type = request.getParameter("type");
			String key = request.getParameter("key");
			List<Customer> customers = customerService.export(type, key);
			if (customers == null || customers.size() == 0) {
				errorMsg = "不存在导出数据";
			} else {
				fileName = "customer" + DateUtils.getDate("yyyyMMddHHmmss")
						+ ".xls";
				writeFile = new ExportExcel("客户数据", Customer.class, 1)
						.setDataList(customers);
				writeFile.write(response, fileName);
				return null;
			}
		} catch (Exception e) {
			addMessage(redirectAttributes, errorMsg);
		} finally {
			if (writeFile != null) {
				writeFile.dispose();
			}
		}
		System.out.println(fileName);
		return "redirect:" + Global.ADMIN_PATH + "/base/customer/";
	}

	@ResponseBody
	@RequestMapping(value = "import", method = RequestMethod.POST)
	public String importFile(MultipartFile file,
			RedirectAttributes redirectAttributes) {
		int successNum = 0;
		int failureNum = 0;
		StringBuilder failureMsg = new StringBuilder();
		try {
			ImportExcel ei = new ImportExcel(file, 1, 0);
			List<Customer> list = ei.getDataList(Customer.class);
			for (Customer customer : list) {
				if (customer.getName() == null) {
					continue;
				}
				try {
					if ("true".equals(isExist(null, customer.getMobile()))) {
						customer.setGender(0);
						customer.setStore(StoreUtils.getStore());
						BeanValidators.validateWithException(validator,
								customer);
						customerService.save(customer);
						successNum++;
					} else {
						failureMsg.append("客户 " + customer.getName()
								+ " 已存在; ");
						failureNum++;
					}
				} catch (ConstraintViolationException ex) {
					failureMsg.append("客户 " + customer.getName() + " ");
					List<String> messageList = BeanValidators
							.extractPropertyAndMessageAsList(ex, ": ");
					for (String message : messageList) {
						failureMsg.append(message + "; ");
						failureNum++;
					}
				} catch (Exception ex) {
					failureMsg.append("客户 " + customer.getName()
							+ " 导入失败");
				}
			}
		} catch (Exception e) {
			System.err.println(e.getMessage());
		}
		Map<String, String> map = Maps.newHashMap();
		map.put("successNum", successNum + "");
		map.put("failureNum", failureNum + "");
		map.put("errorMsg", failureMsg.toString());
		return JsonMapper.getInstance().toJson(map);
	}

	@RequestMapping(value = "import/template")
	public String importFileTemplate(HttpServletResponse response,
			RedirectAttributes redirectAttributes) {
		ExportExcel write = null;
		try {
			String fileName = "客户导入模板.xls";
			List<Customer> list = Lists.newArrayList();
			Customer c = new Customer();
			c.setName("用户名");
			c.setBirthday(new Date());
			c.setMobile("手机号");
			list.add(c);
			write = new ExportExcel("客户数据", Customer.class, 2).setDataList(list);
			write.write(response, fileName);		
			return null;
		} catch (Exception e) {
			addMessage(redirectAttributes, "导入模板下载失败！失败信息：" + e.getMessage());
		} finally{
			if (write != null) {
				write.dispose();
			}
		}
		return "redirect:" + Global.ADMIN_PATH + "/base/customer/";
	}

	@ResponseBody
	@RequestMapping(value = "allCustomers")
	public String allCustomers(HttpServletResponse response) {
		response.setContentType("application/json; charset=UTF-8");
		Map<Long, String> storeCustomerList = StoreUtils.getStoreCustomerList();
		return JsonMapper.getInstance().toJson(storeCustomerList);
	}

	public String isExist(Long id, String mobile) {
		List<Customer> list = customerService.isUnique(mobile);
		if (list == null || list.size() == 0) {
			return "true";
		}
		if (list.size() == 1) {
			Customer customer = list.get(0);
			if (customer.getId().equals(id)) {
				return "true";
			}
		}
		return "false";
	}
	
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@ResponseBody
	@RequestMapping(value = "isExist")
	public String isExist(HttpServletResponse response, Long id, String mobile) {
		response.setContentType("application/json; charset=UTF-8");
		List<Customer> list = customerService.isUnique(mobile);
		if (id == null) {
			if (list == null || list.size() == 0) {
				return "true";
			}
		} else {
			if (list == null) {
				return "true";
			} else {
				if(list.size() < 2 ){
					return "true";
				}
			}
		}
		if(list.size() > 1 ){
			Collections.sort(list, new Comparator() {  
		        @Override  
		        public int compare(Object o1, Object o2) {  
		            if (o1 instanceof Customer  
		                    && o2 instanceof Customer) {  
		            	Customer s1 = (Customer) o1;  
		            	Customer s2 = (Customer) o2;  
		                return s2.getStore().getId().compareTo(s1.getStore().getId());  
		            }  
		            return 0;  
		        }  
		          
		    });
		}
		List<Map<String, Object>> set = Lists.newLinkedList();
		for (Customer customer : list) {
			Map<String, Object> map = Maps.newHashMap();
			Store store = customer.getStore();
			map.put("id", customer.getId());
			map.put("storeId", store.getId());
			map.put("storeName", store.getName());
			map.put("areaName", store.getArea().getName());
			map.put("mobile", customer.getMobile());
			map.put("name", customer.getName());
			map.put("nickName", customer.getNickname() == null ? "" : customer.getNickname());
			set.add(map);
		}
		return JsonMapper.getInstance().toJson(set);
	}

	@ResponseBody
	@RequestMapping(value = "deleteFile")
	public String deleteFile(String fileName) {
		boolean msg = false;
		try {
			String filePath = FileUtils.getWebRoot() + "/temp/" + fileName;
			boolean succeed = FileUtils.deleteFile(filePath);
			msg = succeed;
		} catch (Exception e) {
		}
		Map<String, Boolean> map = Maps.newHashMap();
		map.put("msg", msg);
		return JsonMapper.getInstance().toJson(map);
	}

	@ResponseBody
	@RequestMapping(value = "customerData")
	public String customerData(@RequestParam(required = false) Long extId,
			HttpServletResponse response) {
		response.setContentType("application/json; charset=UTF-8");
		Set<Map<String, Object>> set = Sets.newHashSet();
		List<Customer> customerList = customerService.getByStore();
		for (Customer customer : customerList) {
			Map<String, Object> map = Maps.newHashMap();
			map.put("id", customer.getId());
			map.put("mobile", customer.getMobile());
			map.put("name", customer.getName());
			map.put("nickName", customer.getNickname());
			set.add(map);
		}
		return JsonMapper.getInstance().toJson(set);
	}
}
